﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="IndexDefinitionServiceTests.cs" company="DST Nexdox">
//   Copyright (c) DST Nexdox. All rights reserved.
// </copyright>
// <summary>
//   Defines the IndexDefinitionServiceTests type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ServiceTests
{
  using System;
  using System.Collections.Generic;
  using DocProcessingRepository.Interfaces;
  using Entities;
  using Exceptions;
  using FluentAssertions;
  using Moq;
  using NUnit.Framework;
  using ServiceInterfaces;
  using Services;

  [Category("Unit")]
  [TestFixture]
  public class IndexDefinitionServiceTests
  {
    private IIndexDefinitionService indexDefinitionService;

    private Mock<IIndexDefinitionRepository> indexDefinitionRepositoryMock;

    private Mock<IUserService> userServiceMock;

    private Mock<IMediaDefinitionAuditService> mediaDefinitionAuditServiceMock;

    private Mock<IMailSortSettingService> mailSortSettingServiceMock;

    private ApplicationUser currentUser;

    [SetUp]
    public void SetUp()
    {
      this.indexDefinitionRepositoryMock = new Mock<IIndexDefinitionRepository>();
      this.userServiceMock = new Mock<IUserService>();
      this.mediaDefinitionAuditServiceMock = new Mock<IMediaDefinitionAuditService>();
      this.mailSortSettingServiceMock = new Mock<IMailSortSettingService>();

      this.indexDefinitionService = new IndexDefinitionService(
        this.indexDefinitionRepositoryMock.Object,
        this.userServiceMock.Object,
        this.mediaDefinitionAuditServiceMock.Object,
        this.mailSortSettingServiceMock.Object);

      this.currentUser = new ApplicationUser("Username") { PreferredEnvironment = "Test" };
    }

    [Test]
    public void GivenValidData_WhenIUpdateTheMailSortSetting_TheDatabaseIsUpdated()
    {
      var mailSortSettings = new List<MailsortSetting> { new MailsortSetting { MailsortSettingID = 2, nexdoxMailsortService = "MailSortSettingName" } };

      this.userServiceMock.Setup(u => u.GetApplicationUser()).Returns(this.currentUser);
      this.mailSortSettingServiceMock.Setup(m => m.GetMailsortSettings()).Returns(mailSortSettings);

      this.indexDefinitionService.UpdateMailSortSetting(1, 2);

      this.indexDefinitionRepositoryMock.Verify(i => i.UpdateMailSortSetting(1, 2), Times.Once);

      this.mediaDefinitionAuditServiceMock.Verify(
        a =>
        a.AddAudit(
          1,
          this.currentUser.Id,
          MediaDefinitionAudit.MediaDefinitionAuditType.MailSortSettingUpdated,
          It.IsAny<DateTime>(),
          "MailSortSetting set as 'MailSortSettingName'"),
        Times.Once);
    }

    [Test]
    public void GivenValidData_WhenIClearTheMailSortSetting_TheDatabaseIsUpdated()
    {
      this.userServiceMock.Setup(u => u.GetApplicationUser()).Returns(this.currentUser);

      this.indexDefinitionService.UpdateMailSortSetting(1, 0);

      this.indexDefinitionRepositoryMock.Verify(i => i.UpdateMailSortSetting(1, null), Times.Once);

      this.mediaDefinitionAuditServiceMock.Verify(
        a =>
        a.AddAudit(
          1,
          this.currentUser.Id,
          MediaDefinitionAudit.MediaDefinitionAuditType.MailSortSettingUpdated,
          It.IsAny<DateTime>(),
          "MailSortSetting cleared"),
        Times.Once);
    }

    [Test]
    public void GivenValidData_WhenIUpdateTheMailSortSetting_AndTheDatabaseIsUnavailable_ADocProcessingExceptionIsRaised()
    {
      this.indexDefinitionRepositoryMock.Setup(i => i.UpdateMailSortSetting(It.IsAny<Int32>(), It.IsAny<Int32>()))
        .Throws<Exception>();

      Action act = () => this.indexDefinitionService.UpdateMailSortSetting(1, 2);

      act.ShouldThrow<DocProcessingException>();

      this.mediaDefinitionAuditServiceMock.Verify(
        a =>
        a.AddAudit(
          It.IsAny<Int32>(),
          It.IsAny<String>(),
          It.IsAny<MediaDefinitionAudit.MediaDefinitionAuditType>(),
          It.IsAny<DateTime>(),
          It.IsAny<String>()),
        Times.Never);
    }
  }
}
